home *** CD-ROM | disk | FTP | other *** search
/ Mac Format 1997 July / macformat52.iso / mac / Shareware Plus / Educational / LEE 2.1 / Source / body.c next >
Text File  |  1996-08-07  |  26KB  |  1,160 lines

  1. /* body.c
  2.  *                         Copyright (1992)
  3.  *
  4.  *          Rik Belew.  University of California, San Diego
  5.  *    Filippo Menczer.  University of California, San Diego
  6.  *        Greg Linden.  University of California, San Diego
  7.  *
  8.  *        This software may be redistributed without charge;
  9.  *                 this notice should be preserved.
  10.  */
  11.  
  12.  
  13. #include "defs.h"
  14. #include <math.h>
  15.  
  16.  
  17. /*    Given a heading, moveDiff() returns the
  18.     shift in the current position needed to
  19.     take one step in that direction.  This
  20.     can then be multiplied by a scalar to
  21.     do larger moves in that direction. */
  22.  
  23. position
  24. moveDiff (heading)
  25.     int        heading;
  26. {
  27.     position    thePosition;
  28.  
  29.  
  30.     switch (heading) {
  31.         case UP:
  32.             thePosition.x = 0;
  33.             thePosition.y = 1;
  34.             break;
  35.         case DOWN:
  36.             thePosition.x = 0;
  37.             thePosition.y = -1;
  38.             break;
  39.         case LEFT:
  40.             thePosition.x = -1;
  41.             thePosition.y = 0;
  42.             break;
  43.         case RIGHT:
  44.             thePosition.x = 1;
  45.             thePosition.y = 0;
  46.             break;
  47.         default:
  48.             printf("Error in moveDiff().  Undefined direction.\n");
  49.             exit(1);
  50.     }
  51.  
  52.     return (thePosition);
  53. }
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60. /*    Given the horizontal and vertical
  61.     distance to a cell, returns the position of
  62.     the new cell from the initial position,
  63.     compensating for the toroidal world. */
  64.  
  65. position
  66. find_cell (coordinates, delta) 
  67.     position        coordinates,delta;
  68. {
  69.     position        newCell;
  70.  
  71.     newCell.x = coordinates.x;
  72.     newCell.y = coordinates.y;
  73.  
  74.     newCell.x+=delta.x;
  75.     if (newCell.x<0)
  76.         newCell.x+=x_dim;
  77.     else if (newCell.x>=x_dim)
  78.         newCell.x-=x_dim;
  79.  
  80.     newCell.y+=delta.y;
  81.     if (newCell.y<0)
  82.         newCell.y+=y_dim;
  83.     else if (newCell.y>=y_dim)
  84.         newCell.y-=y_dim;
  85.  
  86.     return (newCell);
  87. }
  88.  
  89.  
  90.  
  91.  
  92.  
  93. /*    range() returns a list of the positions of the cells 
  94.     that are within range of the given sensor */
  95.  
  96. listofPositions *
  97. range(org_pos, org_direction, theSensor)
  98.     position        org_pos;
  99.     int            org_direction;
  100.     sensor            theSensor;
  101. {    
  102.     listofPositions        *rangeList=NIL_POINTER, *temp;
  103.     position        diff;
  104.     int            direction, size;
  105.     register int        i;
  106.  
  107.         
  108.     switch (theSensor.system) {
  109.         case CONTACT:
  110.  
  111.             /* Contact sensor */
  112.             /*    Add the position one move in the heading 
  113.                 direction from the org_pos to the rangeList.  
  114.                 Since the world is torroidal, if the
  115.                 organism is on an edge of the map, this may 
  116.                 require wrapping around the map to the other 
  117.                 side.    */
  118.     
  119.             rangeList = (listofPositions*) malloc (sizeof(listofPositions));
  120.             if (rangeList == NIL_POINTER)
  121.             {
  122.                 printf("\nERROR: rangeList malloc\n");
  123.                 exit(1);
  124.             }
  125.             rangeList->next = NIL_POINTER;
  126.  
  127.             direction = facing(org_direction, theSensor.orientation);
  128.  
  129.  
  130.             diff = moveDiff(direction);
  131.  
  132.             rangeList->current = find_cell(org_pos, diff);
  133.             
  134.             break;
  135.  
  136.         case AMBIENT:
  137.  
  138.             /* Ambient sensor */
  139.             /*    Add the positions around org_pos, depending 
  140.                 on direction of org and orientation of
  141.                 sensor, to the rangeList.  
  142.                 Since the world is torroidal, if the
  143.                 organism is on an edge of the map, this may 
  144.                 require wrapping around the map to the other 
  145.                 side.    */
  146.  
  147.             size = range_size(theSensor.range);
  148.             rangeList = temp = (listofPositions*) malloc(sizeof(listofPositions));
  149.             if (rangeList == NIL_POINTER)
  150.             {
  151.                 printf("\nERROR: rangeList malloc\n");
  152.                 exit(1);
  153.             }
  154.             for (i=0; i<size-1; i++)
  155.             {
  156.                 diff.x = off_vec[1+facing(org_direction,theSensor.orientation)][i]->x;
  157.                 diff.y = off_vec[1+facing(org_direction,theSensor.orientation)][i]->y;
  158.                 temp->current = find_cell(org_pos, diff);
  159.                 temp->distance = off_vec[1+facing(org_direction,theSensor.orientation)][i]->d;
  160.                 temp->next = (listofPositions*) malloc(sizeof(listofPositions));
  161.                 if (temp->next == NIL_POINTER)
  162.                 {
  163.                     printf("\nERROR: malloc in range()\n");
  164.                     exit(1);
  165.                 }
  166.                 temp = temp->next;
  167.             }
  168.             diff.x = off_vec[1+facing(org_direction,theSensor.orientation)][size-1]->x;
  169.             diff.y = off_vec[1+facing(org_direction,theSensor.orientation)][size-1]->y;
  170.             temp->current = find_cell(org_pos, diff);
  171.             temp->distance = off_vec[1+facing(org_direction,theSensor.orientation)][size-1]->d;
  172.             temp->next = NIL_POINTER;
  173.             break;
  174.  
  175.         default:
  176.             printf("\nError:  Unknown sensor in range().\n");
  177.             exit(1);
  178.     }
  179.  
  180.     return(rangeList);
  181. }
  182.  
  183. /*
  184.  * number of cells in range of ambient sensor
  185.  */
  186. int range_size(range)
  187.  
  188.     int range;
  189. {
  190.     if (range == 1) return(1);
  191.     else return(2*range*range - 4*range + 4); 
  192. }
  193.  
  194. /*
  195.  * scales the distance (measured in number of steps)
  196.  * before its inverse is used to weigh the signal
  197.  * produced by an ambient sensor, eg, so that inputs
  198.  * aren't too week on average (flat part of logistic)
  199.  */
  200. float scale(n)
  201.  
  202.     int n;
  203. {
  204.     /*
  205.      * weight large for n=1 (scale slope > 1)
  206.      * weight flat  for n>1 (scale slope < 1)
  207.      * 2.5 is needed to avoid division by 0
  208.      *  (any number > log(.1) works the same 
  209.      *   given the subsequent normalization...)
  210.      * 0.9 is needed to get slope > 1 for n=1
  211.      *  (any number s.t. 0 < number < 1 works)
  212.      *
  213.     return ((float)n);
  214.     return ((float)log((double)(n + 1)));
  215.      */
  216.     return (2.5 + (float)log((double)n - 0.9));
  217. }
  218.  
  219. /*
  220.  * loads the global offset array off_vec for ambient sensors
  221.  *     and norm_dist[] for normalization (sum of distances).
  222.  * NOTE 1: following Greg's convention, UP <=> y increasing
  223.  * NOTE 2: since facing() returns absolute direction of sensor
  224.  *         field and not org facing direction, we decided that
  225.  *         distance is relative to sensor absolute orientation: 
  226.  *         it doesn't count minimal number of steps, but
  227.  *         rather ditance from sensor "location" (defined
  228.  *         as absolute orientation).
  229.  */
  230. void carica_offsets(range)
  231.  
  232.     int range;
  233. {
  234.     int r;
  235.     register int i,j;
  236.  
  237.     if (range == 1) 
  238.     {
  239.         off_vec[0][0]->x = -1;
  240.         off_vec[0][0]->y = 0;
  241.         off_vec[0][0]->d = scale(range);
  242.         off_vec[1][0]->x = 0;
  243.         off_vec[1][0]->y = 1;
  244.         off_vec[1][0]->d = scale(range);
  245.         off_vec[2][0]->x = 1;
  246.         off_vec[2][0]->y = 0;
  247.         off_vec[2][0]->d = scale(range);
  248.         off_vec[3][0]->x = 0;
  249.         off_vec[3][0]->y = -1;
  250.         off_vec[3][0]->d = scale(range);
  251.  
  252.         r = range_size(range);
  253.         for (i=0; i<r; i++) norm_dist[range-1] += 1.0/off_vec[0][i]->d;
  254.     }
  255.     else if (range == 2) 
  256.     {
  257.         carica_offsets(1);
  258.  
  259.         off_vec[0][1]->x = -2;
  260.         off_vec[0][1]->y = 0;
  261.         off_vec[0][1]->d = scale(range);
  262.         off_vec[1][1]->x = 0;
  263.         off_vec[1][1]->y = 2;
  264.         off_vec[1][1]->d = scale(range);
  265.         off_vec[2][1]->x = 2;
  266.         off_vec[2][1]->y = 0;
  267.         off_vec[2][1]->d = scale(range);
  268.         off_vec[3][1]->x = 0;
  269.         off_vec[3][1]->y = -2;
  270.         off_vec[3][1]->d = scale(range);
  271.  
  272.         off_vec[0][2]->x = 0;
  273.         off_vec[0][2]->y = -1;
  274.         off_vec[0][2]->d = scale(range);
  275.         off_vec[1][2]->x = -1;
  276.         off_vec[1][2]->y = 0;
  277.         off_vec[1][2]->d = scale(range);
  278.         off_vec[2][2]->x = 0;
  279.         off_vec[2][2]->y = 1;
  280.         off_vec[2][2]->d = scale(range);
  281.         off_vec[3][2]->x = 1;
  282.         off_vec[3][2]->y = 0;
  283.         off_vec[3][2]->d = scale(range);
  284.  
  285.         off_vec[0][3]->x = 0;
  286.         off_vec[0][3]->y = 1;
  287.         off_vec[0][3]->d = scale(range);
  288.         off_vec[1][3]->x = 1;
  289.         off_vec[1][3]->y = 0;
  290.         off_vec[1][3]->d = scale(range);
  291.         off_vec[2][3]->x = 0;
  292.         off_vec[2][3]->y = -1;
  293.         off_vec[2][3]->d = scale(range);
  294.         off_vec[3][3]->x = -1;
  295.         off_vec[3][3]->y = 0;
  296.         off_vec[3][3]->d = scale(range);
  297.  
  298.         r = range_size(range);
  299.         for (i=0; i<r; i++) norm_dist[range-1] += 1.0/off_vec[0][i]->d;
  300.     }
  301.     else 
  302.     {
  303.         carica_offsets(range-1);
  304.         r = range_size(range-1);
  305.  
  306.         off_vec[0][r]->x = -range;
  307.         off_vec[0][r]->y = 0;
  308.         off_vec[0][r]->d = scale(range);
  309.         off_vec[1][r]->x = 0;
  310.         off_vec[1][r]->y = range;
  311.         off_vec[1][r]->d = scale(range);
  312.         off_vec[2][r]->x = range;
  313.         off_vec[2][r]->y = 0;
  314.         off_vec[2][r]->d = scale(range);
  315.         off_vec[3][r]->x = 0;
  316.         off_vec[3][r]->y = -range;
  317.         off_vec[3][r]->d = scale(range);
  318.         
  319.         r++;
  320.  
  321.         off_vec[0][r]->x = range-2;
  322.         off_vec[0][r]->y = 0;
  323.         off_vec[0][r]->d = scale(range);
  324.         off_vec[1][r]->x = 0;
  325.         off_vec[1][r]->y = 2-range;
  326.         off_vec[1][r]->d = scale(range);
  327.         off_vec[2][r]->x = 2-range;
  328.         off_vec[2][r]->y = 0;
  329.         off_vec[2][r]->d = scale(range);
  330.         off_vec[3][r]->x = 0;
  331.         off_vec[3][r]->y = range-2;
  332.         off_vec[3][r]->d = scale(range);
  333.  
  334.         for (i=1, j=3-range; i<=range-3; i++, j++)
  335.         {
  336.             r++;
  337.  
  338.             off_vec[0][r]->x = -j;
  339.             off_vec[0][r]->y = -i;
  340.             off_vec[0][r]->d = scale(range);
  341.             off_vec[1][r]->x = -i;
  342.             off_vec[1][r]->y = j;
  343.             off_vec[1][r]->d = scale(range);
  344.             off_vec[2][r]->x = j;
  345.             off_vec[2][r]->y = i;
  346.             off_vec[2][r]->d = scale(range);
  347.             off_vec[3][r]->x = i;
  348.             off_vec[3][r]->y = -j;
  349.             off_vec[3][r]->d = scale(range);
  350.  
  351.             r++;
  352.  
  353.             off_vec[0][r]->x = -j;
  354.             off_vec[0][r]->y = i;
  355.             off_vec[0][r]->d = scale(range);
  356.             off_vec[1][r]->x = i;
  357.             off_vec[1][r]->y = j;
  358.             off_vec[1][r]->d = scale(range);
  359.             off_vec[2][r]->x = j;
  360.             off_vec[2][r]->y = -i;
  361.             off_vec[2][r]->d = scale(range);
  362.             off_vec[3][r]->x = -i;
  363.             off_vec[3][r]->y = -j;
  364.             off_vec[3][r]->d = scale(range);
  365.         }
  366.  
  367.         for (i=1, j=range-2; i<=range-1; i++, j--)
  368.         {
  369.             r++;
  370.  
  371.             off_vec[0][r]->x = -j;
  372.             off_vec[0][r]->y = -i;
  373.             off_vec[0][r]->d = scale(range);
  374.             off_vec[1][r]->x = -i;
  375.             off_vec[1][r]->y = j;
  376.             off_vec[1][r]->d = scale(range);
  377.             off_vec[2][r]->x = j;
  378.             off_vec[2][r]->y = i;
  379.             off_vec[2][r]->d = scale(range);
  380.             off_vec[3][r]->x = i;
  381.             off_vec[3][r]->y = -j;
  382.             off_vec[3][r]->d = scale(range);
  383.  
  384.             r++;
  385.  
  386.             off_vec[0][r]->x = -j;
  387.             off_vec[0][r]->y = i;
  388.             off_vec[0][r]->d = scale(range);
  389.             off_vec[1][r]->x = i;
  390.             off_vec[1][r]->y = j;
  391.             off_vec[1][r]->d = scale(range);
  392.             off_vec[2][r]->x = j;
  393.             off_vec[2][r]->y = -i;
  394.             off_vec[2][r]->d = scale(range);
  395.             off_vec[3][r]->x = -i;
  396.             off_vec[3][r]->y = -j;
  397.             off_vec[3][r]->d = scale(range);
  398.         }
  399.         r = range_size(range);
  400.         for (i=0; i<r; i++) norm_dist[range-1] += 1.0/off_vec[0][i]->d;
  401.     }
  402. }
  403.  
  404.  
  405. void
  406. killListOfPos (list_pointer)
  407.     listofPositions        *list_pointer;
  408. {
  409.     listofPositions     *thePtr = list_pointer, *oldPtr;
  410.     
  411.     oldPtr = thePtr;
  412.     while (thePtr!=NIL_POINTER) {
  413.         thePtr = thePtr->next;
  414.         free((char *) oldPtr);
  415.         oldPtr = thePtr;
  416.     }
  417. }
  418.  
  419.  
  420.  
  421.  
  422.  
  423.  
  424. /*    check_world() returns a list of the cells that 
  425.     contain atoms that can be sensed by the given 
  426.     sensor of the organism.  
  427.  
  428.     Thanks to Federico Cecconi and Virginia Games.
  429. */
  430.  
  431. listofPositions*
  432. check_world (org_pos, org_direction, theSensor)
  433.     position        org_pos;
  434.     int            org_direction;
  435.     sensor            theSensor;
  436. {
  437.     listofPositions     *sensedCells=NIL_POINTER, *rangeList, *temp, *p;
  438.     cell            *cellPointer;
  439.     boolean            detectable=FALSE;
  440.     
  441.     switch (theSensor.system) {
  442.         case CONTACT:
  443.             rangeList = range (org_pos, org_direction, theSensor);
  444.  
  445.  
  446.             /*********************
  447.             for (each item in rangeList) {
  448.                 Check if sensor can detect atoms at 
  449.                     position.  If not or position 
  450.                     empty, delete from rangeList.
  451.             }
  452.             ********************/
  453.  
  454.             detectable=FALSE;
  455.             if (rangeList==NIL_POINTER) {
  456.                 printf("NIL returned by range().\n");
  457.                 exit(1);
  458.             }
  459.             else {
  460.                 cellPointer = world[rangeList->current.x][rangeList->current.y];
  461.  
  462.                 while ((cellPointer!=NIL_POINTER) && (!detectable)){
  463.                     if (cellPointer->type == food)
  464.                         if (theSensor.complex[cellPointer->datum.atom]!=0)
  465.                             detectable=TRUE;
  466.                     cellPointer=cellPointer->next;
  467.                 }
  468.  
  469.                 if (detectable)
  470.                     sensedCells = rangeList;
  471.                 else 
  472.                     killListOfPos(rangeList);
  473.             }
  474.             break;
  475.  
  476.         case AMBIENT:
  477.             sensedCells = rangeList = temp = range (org_pos, org_direction, theSensor);
  478.             if (rangeList==NIL_POINTER) {
  479.                 printf("NIL returned by range().\n");
  480.                 exit(1);
  481.             }
  482.             else 
  483.             {
  484.                 while (rangeList!=NIL_POINTER)
  485.                 {
  486.                     detectable=FALSE;
  487.                     cellPointer = world[rangeList->current.x][rangeList->current.y];
  488.                     while ((cellPointer!=NIL_POINTER) && (!detectable))
  489.                     {
  490.                         if (cellPointer->type == food)
  491.                             if (theSensor.complex[cellPointer->datum.atom]!=0)
  492.                                 detectable=TRUE;
  493.                         cellPointer=cellPointer->next;
  494.                     }
  495.                     if (temp == rangeList)
  496.                     {
  497.                         rangeList = rangeList->next;
  498.                         if (!detectable) 
  499.                         {
  500.                             /* killListOfPos(temp); */
  501.                             p = temp;
  502.                             free(p);
  503.                             sensedCells = temp = rangeList;
  504.                         }
  505.                     }
  506.                     else
  507.                     {
  508.                         if (!detectable) 
  509.                         {
  510.                             rangeList = rangeList->next;
  511.                             /* killListOfPos(temp->next); */
  512.                             p = temp->next;
  513.                             free(p);
  514.                             temp->next = rangeList;
  515.                         }
  516.                         else 
  517.                         {
  518.                             temp = rangeList;
  519.                             rangeList = rangeList->next;
  520.                         }
  521.                     }
  522.                 }
  523.             }
  524.             break;
  525.         default:
  526.             printf("\nError:  Unknown sensor type in check_world();.\n");
  527.             exit(1);
  528.     }
  529.         
  530.     return (sensedCells);
  531. }
  532.  
  533.  
  534.  
  535.  
  536.  
  537.  
  538.  
  539.  
  540. /*    Modifies the activity level of the input nodes of 
  541.     the neural network on the appropriate sensor 
  542.     according to what the sensor has detected.  
  543.  
  544.     Thanks to Federico Cecconi and Virginia Games.
  545. */
  546.  
  547. void
  548. sense (org_pos, org_direction, theSensor, theGut, activity_levels) 
  549.  
  550.     position        org_pos;
  551.     int            org_direction;
  552.     sensor            theSensor;
  553.     int            theGut[];    /* error if used constant MAXTYPES for dimension */
  554.     float            *activity_levels;
  555. {
  556.     listofPositions    *sensedCells=NIL_POINTER, *rangeList=NIL_POINTER;
  557.     float        trigger = 0.0;
  558.     cell        *cellPointer = NIL_POINTER;
  559.     int        counter;
  560.     boolean        maskCheck=FALSE;
  561.     boolean        detectedYet[MAXTYPES];
  562.  
  563.  
  564.  
  565.  
  566.     /* Get the level of firing of the input for the sensor
  567.       (assumes only one input node currently)  */
  568.     switch (theSensor.system) {
  569.         case GUT_SENSOR:
  570.             for (counter=0; counter<types;counter++) 
  571.                 if (theGut[counter]>0)
  572.                     trigger += theSensor.complex[counter];
  573.             break;
  574.         case CONTACT: 
  575.             for (counter=0;counter<types; counter++) detectedYet[counter] = FALSE;
  576.             sensedCells = check_world (org_pos, org_direction, theSensor);
  577.             rangeList = sensedCells;
  578.             if (sensedCells!=NIL_POINTER) {
  579.  
  580.                 /* Add levels of triggering of the sensor.
  581.                       Only detect presense 
  582.                    of atoms, not number.  */
  583.  
  584.                 cellPointer = world[sensedCells->current.x][sensedCells->current.y];
  585.                 while (cellPointer!=NIL_POINTER) {
  586.                     if (cellPointer->type == food)
  587.                         if (!detectedYet[cellPointer->datum.atom]) {
  588.                             trigger+=theSensor.complex[cellPointer->datum.atom];
  589.                             detectedYet[cellPointer->datum.atom]=TRUE;
  590.                         }
  591.                     cellPointer = cellPointer->next;
  592.                 }
  593.             }
  594.             break;
  595.         case AMBIENT:
  596.             sensedCells = check_world (org_pos, org_direction, theSensor);
  597.             rangeList = sensedCells;
  598.             while (sensedCells!=NIL_POINTER) {
  599.                 for (counter=0;counter<types; counter++) detectedYet[counter] = FALSE;
  600.                 cellPointer = world[sensedCells->current.x][sensedCells->current.y];
  601.                 while (cellPointer!=NIL_POINTER) {
  602.                     if (cellPointer->type == food)
  603.                         if (!detectedYet[cellPointer->datum.atom]) {
  604.                             trigger+=(theSensor.complex[cellPointer->datum.atom]/sensedCells->distance);
  605.                             detectedYet[cellPointer->datum.atom]=TRUE;
  606.                         }
  607.                     cellPointer = cellPointer->next;
  608.                 }
  609.                 sensedCells = sensedCells->next;
  610.             }
  611.             break;
  612.         default:
  613.             printf("Error:  Unknown sensor type.\n");
  614.             exit(1);
  615.     }
  616.  
  617.  
  618.     /* Normalize the trigger level to 1 and max out at 1. 
  619.        Place the final firing value for the input node in
  620.        an array that represents the input nodes of the 
  621.        neural network.  */
  622.  
  623.     switch (theSensor.system) {
  624.         case AMBIENT:
  625.             trigger/=norm_dist[theSensor.range];
  626.         case GUT_SENSOR:
  627.         case CONTACT:
  628.             trigger/=COMPLEX_SIZE;
  629.  
  630.             for (counter=0; counter<(*layer_descp);counter++) 
  631.                 if (theSensor.mask[counter]!=0) {
  632.                     activity_levels[counter] = trigger;
  633.                     if (maskCheck) {
  634.                         printf("\nSensor masking to more than one input!\nCode is not designed for this.\n");
  635.                         exit(1);
  636.                     }
  637.                     else 
  638.                         maskCheck = TRUE;
  639.                 }
  640.             break;
  641.  
  642.         default:
  643.             printf("Error:  Unknown sensor type.\n");
  644.             exit(1);
  645.     }
  646.  
  647.     /* killListOfPos(sensedCells); */
  648.     killListOfPos(rangeList);
  649. }
  650.     
  651.  
  652.  
  653. /*  Sense the world using all the sensors (which place
  654.     their firing levels for their input nodes in a temporary
  655.     array), combine all their inputs, and place
  656.     the combined input to the network in the network.  */
  657.  
  658. void    
  659. sense_world (organism)
  660.     struct indiv    *organism;
  661. {
  662.     int        x,y;
  663.     float        *new_levels, *activity_levels;
  664.     position    org_pos;
  665.     int        numInputs = (*layer_descp);
  666.  
  667.  
  668.     org_pos.x=organism->worldx;
  669.     org_pos.y=organism->worldy;
  670.  
  671.     activity_levels = (float *) malloc(NINPUTS * sizeof(float));
  672.     new_levels = (float *) malloc(NINPUTS * sizeof(float));
  673.     if ((activity_levels == NIL_POINTER) || (new_levels == NIL_POINTER))
  674.     {
  675.         printf("\nERROR: levels malloc\n");
  676.         exit(1);
  677.     }
  678.  
  679.     for (x=0; x<numInputs; x++) 
  680.         *(activity_levels + x) = 0;
  681.  
  682.     
  683.     /* Total the values that the individual sensors will
  684.         place on the inputs of the neural net */
  685.  
  686.     for (x=0; x<nsensors; x++) {
  687.         for (y=0; y<numInputs; y++) 
  688.             *(new_levels + y) = 0;
  689.  
  690.         sense(org_pos, organism->direction, organism->sensor_specs[x], organism->gut, new_levels);
  691.  
  692.         for (y=0;y<numInputs; y++) 
  693.             activity_levels[y]+=new_levels[y];
  694.     }
  695.  
  696.  
  697.     /* Put activity_levels vector as values on inputs of neural network */
  698.  
  699.     for (x=0; x<numInputs; x++)
  700.         *(*(organism->layerp)+x) = activity_levels[x];
  701.  
  702.  
  703.     free((char *) activity_levels);
  704.     free((char *) new_levels);
  705.     
  706. }
  707.  
  708.  
  709.  
  710.  
  711.  
  712.  
  713. /*    Given the direction of the organism and the
  714.     location of the sensor/motor, calculates the 
  715.     absolute facing of that unit.  This can then
  716.     be used to determine the direction of 
  717.     movement/sensing. */
  718.  
  719.  
  720. int
  721. facing (org_direction, object_loc)
  722.     int         org_direction, object_loc;
  723. {
  724.     int        heading;
  725.     switch (object_loc) {
  726.         case BACKWARD:
  727.             switch (org_direction) {
  728.                 case UP:
  729.                     heading = DOWN;
  730.                     break;
  731.                 case DOWN:
  732.                     heading = UP;
  733.                     break;
  734.                 case LEFT:
  735.                     heading = RIGHT;
  736.                     break;
  737.                 case RIGHT:
  738.                     heading = LEFT;
  739.                     break;
  740.                 default:
  741.                     printf("Error in facing().  Undefined direction.\n");
  742.                     exit(1);
  743.             }
  744.             break;
  745.         case LEFT_SIDE:
  746.             switch (org_direction) {
  747.                 case UP:
  748.                     heading = LEFT;
  749.                     break;
  750.                 case DOWN:
  751.                     heading = RIGHT;
  752.                     break;
  753.                 case LEFT:
  754.                     heading = DOWN;
  755.                     break;
  756.                 case RIGHT:
  757.                     heading = UP;
  758.                     break;
  759.                 default:
  760.                     printf("Error in facing().  Undefined direction.\n");
  761.                     exit(1);
  762.             }
  763.             break;
  764.         case RIGHT_SIDE:
  765.             switch (org_direction) {
  766.                 case UP:
  767.                     heading = RIGHT;
  768.                     break;
  769.                 case DOWN:
  770.                     heading = LEFT;
  771.                     break;
  772.                 case LEFT:
  773.                     heading = UP;
  774.                     break;
  775.                 case RIGHT:
  776.                     heading = DOWN;
  777.                     break;
  778.                 default:
  779.                     printf("Error in facing().  Undefined direction.\n");
  780.                     exit(1);
  781.             }
  782.             break;
  783.         case FORWARD:
  784.             heading = org_direction;
  785.             break;
  786.         default:
  787.             printf("Error in facing().  Undefined location.\n");
  788.             exit(1);
  789.     }
  790.  
  791.     return (heading);
  792. }
  793.  
  794.  
  795.  
  796.  
  797.  
  798.  
  799.  
  800. /*    Returns the change in position that a jump motor 
  801.     produces */
  802.  
  803. position 
  804. jumpMotorMove (outputLayer, numOutputs, theMotor, newFacing) 
  805.     float*            outputLayer;
  806.     int            numOutputs;
  807.     motor            theMotor;
  808.     int            *newFacing;    /* Pass by location */
  809. {
  810.     position    diff;
  811.     int        org_direction = *newFacing;
  812.     int        index, dist;
  813.  
  814.  
  815.     diff.x = 0;
  816.     diff.y = 0;
  817.  
  818.     /* A jump motor is based off one continuous value. */
  819.  
  820.     for (index=0; index<numOutputs;index++) 
  821.         if (theMotor.mask[index]==1) {
  822.             dist = (int)((*(outputLayer+index)) * (float)theMotor.power);
  823.             break;
  824.         }
  825.     
  826.     diff = moveDiff(org_direction);
  827.     diff.x *= dist;
  828.     diff.y *= dist;
  829.  
  830.     /* ADD LOCATION OF MOTOR HERE! */
  831.  
  832.     if (rans(1.0) > 0.0)
  833.     {
  834.         if (rans(1.0) > 0.0)
  835.                 *newFacing = facing (org_direction, RIGHT_SIDE);
  836.         else
  837.             *newFacing = facing (org_direction, LEFT_SIDE);
  838.     }
  839.  
  840.     return (diff);
  841. }
  842.  
  843.  
  844.  
  845.  
  846.  
  847. /*    Returns the change in position that a binary motor 
  848.     produces */
  849.  
  850. position 
  851. binaryMotorMove (outputLayer, numOutputs, theMotor, newFacing) 
  852.     float*            outputLayer;
  853.     int            numOutputs;
  854.     motor            theMotor;
  855.     int            *newFacing;    /* Pass by location */
  856. {
  857.     position    diff;
  858.     int        org_direction = *newFacing;
  859.     int        command=0, index, bin_val=2;
  860.  
  861.  
  862.     diff.x = 0;
  863.     diff.y = 0;
  864.  
  865.     /* A binary motor is based off two bit values.  
  866.        The masked values must be converted.  Anything
  867.            above .5 will be considered 1 */
  868.  
  869.     for (index=0; index<numOutputs;index++) 
  870.         if (theMotor.mask[index]==1) {
  871.             if (*(outputLayer+index)>.5) {
  872.                 command+=bin_val;
  873.             }
  874.             bin_val/=2;
  875.             if (bin_val<1)
  876.                 bin_val = 0;
  877.         }
  878.     
  879.  
  880.     switch (command) {
  881.         case 0: 
  882.             break;
  883.         case 1:
  884.                         *newFacing = facing (org_direction, RIGHT_SIDE);
  885.             break;
  886.         case 2:
  887.             *newFacing = facing (org_direction, LEFT_SIDE);
  888.             break;
  889.         case 3:
  890.             /* ADD LOCATION OF MOTOR HERE! */
  891.             diff = moveDiff(org_direction);
  892.             diff.x *= theMotor.power;
  893.             diff.y *= theMotor.power;
  894.             break;
  895.     }
  896.  
  897.  
  898.     return (diff);
  899. }
  900.  
  901.  
  902.  
  903.  
  904. /*    Move the organism as indicated by the neural 
  905.     network */
  906.  
  907. void move (organism) 
  908.     struct indiv    *organism;
  909. {
  910.     int            counter;
  911.     position    org_pos, posDiff, tempDiff, new_pos;
  912.     int            newFacing = organism->direction;
  913.     boolean        isSelected=FALSE, isFound = FALSE;
  914.     cell        *theCell;
  915.     int            orgItemNum = 0;
  916.  
  917.  
  918.  
  919.     org_pos.x=organism->worldx;
  920.     org_pos.y=organism->worldy;
  921.  
  922.     posDiff.x = 0;
  923.     posDiff.y = 0;
  924.     
  925.     theCell = world[org_pos.x][org_pos.y];
  926.     
  927.     while ((theCell->next!=NULL) && (!isFound)) {
  928.         if ((theCell->type==org) && (theCell->datum.ap==organism))
  929.             isFound = TRUE;
  930.         else {
  931.             theCell = theCell->next;
  932.             orgItemNum++;
  933.         }
  934.     }
  935.     
  936.     if ((theCell->type!=org) || (theCell->datum.ap!=organism)) {
  937.         printf("Couldn't find the organism in the cell!\n");
  938.         exit(1);
  939.     }
  940.  
  941.  
  942.     /* Motor movements are additive to form
  943.        total movement */
  944.  
  945.     for (counter=0; counter<nmotors; counter++) {
  946.         switch (organism->motor_specs[counter].system) {
  947.             case BINARY:
  948.                 tempDiff = binaryMotorMove(*(organism->layerp+nlayers-1), 
  949.                     (*(layer_descp+nlayers-1)), 
  950.                     organism->motor_specs[counter], 
  951.                     &newFacing);
  952.                 posDiff.x += tempDiff.x;
  953.                 posDiff.y += tempDiff.y;
  954.  
  955.                 organism->energy -= ENERGY_USE;
  956.                 break;
  957.             case JUMP:
  958.                 tempDiff = jumpMotorMove(*(organism->layerp+nlayers-1), 
  959.                     (*(layer_descp+nlayers-1)), 
  960.                     organism->motor_specs[counter], 
  961.                     &newFacing);
  962.                 posDiff.x += tempDiff.x;
  963.                 posDiff.y += tempDiff.y;
  964.  
  965.                 organism->energy -= ENERGY_USE;
  966.                 break;
  967.             default:
  968.                 printf("Unknown motor type!");
  969.                 exit(1);
  970.         }
  971.     }
  972.  
  973.     new_pos = find_cell(org_pos, posDiff);
  974.  
  975.     if ((new_pos.x!=organism->worldx) || (new_pos.y!=organism->worldy)) {
  976.  
  977.         moveInteractiveLasso(orgItemNum, &isSelected, organism);
  978.         
  979.         del_org(organism);
  980.             
  981.         organism->worldx = new_pos.x;
  982.         organism->worldy = new_pos.y;
  983.         organism->direction = newFacing;
  984.         
  985.         ins_org(organism);
  986.         
  987.         moveInteractDrawSelectFrame(isSelected, new_pos);
  988.  
  989.     }
  990.     else 
  991.         organism->direction = newFacing;
  992. }
  993.  
  994.  
  995.  
  996. /*    Given two cells, computes the horizontal
  997.     and vertical distance between them, 
  998.     compensating for the toroidal world. */
  999.  
  1000. position    distance (initCell,finalCell)
  1001.     position    initCell, finalCell;
  1002. {
  1003.     position    diff;
  1004.     int        deltaX, deltaY;
  1005.  
  1006.     deltaX = finalCell.x - initCell.x;
  1007.     deltaY = finalCell.y - initCell.y;
  1008.  
  1009.     if (initCell.x<finalCell.x) {
  1010.         if (deltaX>abs(deltaX - x_dim)) {
  1011.             deltaX -= x_dim;
  1012.         }
  1013.     }
  1014.     else {
  1015.         if (abs(deltaX)>(deltaX+x_dim)) {
  1016.             deltaX += x_dim;
  1017.         }
  1018.     }
  1019.  
  1020.  
  1021.     if (initCell.y<finalCell.y) {
  1022.         if (deltaY>abs(deltaY - y_dim)) {
  1023.             deltaY -= y_dim;
  1024.         }
  1025.     }
  1026.     else {
  1027.         if (abs(deltaY)>(deltaY+y_dim)) {
  1028.             deltaY += y_dim;
  1029.         }
  1030.     }
  1031.  
  1032.     diff.x = deltaX;
  1033.     diff.y = deltaY;
  1034.  
  1035.     return(diff);
  1036. }
  1037.  
  1038.  
  1039.  
  1040. /*
  1041.  * called in populati.c;
  1042.  * returns the number of input units allocated to the sensor
  1043.  */
  1044. sensor_size(system)
  1045.  
  1046.         int system;
  1047. {
  1048.         switch(system)
  1049.         {
  1050.                 case GUT_SENSOR:
  1051.                 case AMBIENT:
  1052.                 case CONTACT:
  1053.                         return(1);
  1054.                         break;
  1055.                 default:
  1056.                         printf("error: sensor system unknown\n");
  1057.                         exit(1);
  1058.         }
  1059. }
  1060.  
  1061.  
  1062.  
  1063.  
  1064.  
  1065. /*
  1066.  * called in populati.c;
  1067.  * returns the number of output units allocated to the motor
  1068.  */
  1069. motor_size(system)
  1070.  
  1071.         int system;
  1072. {
  1073.         switch(system)
  1074.         {
  1075.                 case BINARY:   
  1076.                                 return(2);
  1077.                                 break;
  1078.                 case JUMP:   
  1079.                                 return(1);
  1080.                                 break;
  1081.                 default:        printf("error: motor system unknown\n");
  1082.                                 exit(1);
  1083.         }
  1084. }
  1085.  
  1086.  
  1087.  
  1088. /*
  1089.  * called in populati.c;
  1090.  * returns a sensor/motor mask for new individuals
  1091.  */
  1092. int get_mask(count, size, i)
  1093.  
  1094.         int count;      /* end unit for this mask */
  1095.         int size;       /* number of units for this mask */
  1096.         int i;          /* unit position */
  1097. {
  1098.         if ((i < count) && (i >= (count - size))) return(1);
  1099.         else return(0);
  1100. }
  1101.  
  1102. /*
  1103.  * called in populati.c;
  1104.  * returns a motor power for new individuals
  1105.  */
  1106. int motor_power(system)
  1107.  
  1108.         int system;
  1109. {
  1110.         switch(system)
  1111.         {
  1112.                 case BINARY:   
  1113.                 return(BIN_POWER);
  1114.         case JUMP:
  1115.                 return(JUMP_POWER);
  1116.         default:
  1117.             printf("Error in motor_power().  Undefined sensor type.\n");
  1118.             exit(1);
  1119.     }
  1120. }
  1121.  
  1122.  
  1123.  
  1124. /*
  1125.  * called by mutate() in populati.c;
  1126.  * mutates sensors' complexes and motors' powers
  1127.  * for new individuals:
  1128.  * sensitivity in the sensor complex is shifted
  1129.  * from one atom to another, and the motor power
  1130.  * is added a random integer in [-1,+1] while
  1131.  * kept >= 0;
  1132.  * ATTENTION: for now, orientation and position
  1133.  *            of sensors and motors are not mutated
  1134.  */
  1135. mu_sensorymotor(ap)
  1136.  
  1137.         struct indiv *ap;
  1138. {
  1139.         int             i,j;
  1140.  
  1141.         if ((0.5 + rans(0.5)) < MU_SENSOR_PROB)
  1142.          for (i=0; i<nsensors; i++)
  1143.          {
  1144.                 do {
  1145.                         j = mrand(types);
  1146.                    } while (ap->sensor_specs[i].complex[j] == 0);
  1147.                 --ap->sensor_specs[i].complex[j];
  1148.                 ++ap->sensor_specs[i].complex[mrand(types)];
  1149.          }
  1150.         if ((0.5 + rans(0.5)) < MU_MOTOR_PROB)
  1151.          for (i=0; i<nmotors; i++)
  1152.          {
  1153.                 ap->motor_specs[i].power += (mrand(3) -1);
  1154.                 while (ap->motor_specs[i].power < 0)
  1155.                         ++ap->motor_specs[i].power;
  1156.          }
  1157. }
  1158.  
  1159.  
  1160.